/*
 *  Name		: CMX994.c
 *	Author	 	: Tigran Papazyan
 *  Created on	: Nov 29, 2011
 *  Copyright   : Copyright Antel Systems
 *  Description : CMX994 Driver
 */

#include "CMX994.h"
#include "CMX7164.h"
#include "usart_fast.h"
#include "tc_1.h"
#include "printf-stdarg.h"
#include "LMX2541.h"
#include "AntelCfgOID.h"
#include "CfgParams.h"


int CMX994_Write(unsigned char CMX994_reg_address ,unsigned char data)
{
	spi_talkthrough_write.Word_val = 0x0000 | data ;
	CMX7164_Write_WORD((CMX_WORD*)&spi_talkthrough_write);						//0x63
	spi_talkthrough_address.Word_val = 0x2100 | (CMX994_reg_address & 0x37);
	CMX7164_Write_WORD((CMX_WORD*)&spi_talkthrough_address);					//0x62
	return CMX7164_Check_Status(SPI_Thru_Bit);
}

int CMX994_Read(unsigned char CMX994_reg_address ,unsigned char* data)
{
	if((CMX994_reg_address & 0xF0) == 0x10)
		CMX994_reg_address = (CMX994_reg_address & 0x0F) | 0xE0 ;
	if((CMX994_reg_address & 0xF0) == 0x20)
		CMX994_reg_address = (CMX994_reg_address & 0x0F) | 0xD0 ;

	spi_talkthrough_address.Word_val = 0x3100 | CMX994_reg_address ;
	CMX7164_Write_WORD((CMX_WORD*)&spi_talkthrough_address);
	if(CMX7164_Check_Status(SPI_Thru_Bit))
		return 1 ;
	CMX7164_Read_WORD((CMX_WORD*)&spi_talkthrough_read);
	*data = spi_talkthrough_read.SPI_Read_Data & 0x00FF ;
	return 0;
}

int CMX994_Init(void)
{
	reg_done_select.Word_val = 0x0008 ;			//69	set REG_DONE -> Mode
	CMX7164_Write_WORD((CMX_WORD*)&reg_done_select);

	modem_mode_and_control.Word_val = 0x0070 ;			// Program Block 7
	CMX7164_Write_WORD((CMX_WORD*)&modem_mode_and_control);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;

/*	reg_done_select.Word_val = 0x0001 ;					//69	set REG_DONE -> PROG
	CMX7164_Write_WORD((CMX_WORD*)&reg_done_select);
	programming.Program_Block_Data = 0x0116 ;			//07->00 = 0x0116
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0017 ;			//07->01 = 0x0000
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0116 ;			//07->02 = 0x0116
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0006 ;			//07->03 = 0x0001
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0116 ;			//07->04 = 0x0116
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0005 ;			//07->05 = 0x0002
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0116 ;			//07->06 = 0x0116
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0004 ;			//07->07 = 0x0003
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0116 ;			//07->08 = 0x0116
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0003 ;			//07->09 = 0x0004
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0116 ;			//07->10 = 0x0116
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0002 ;			//07->11 = 0x0005
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0116 ;			//07->12 = 0x0116
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0001 ;			//07->13 = 0x0006
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0116 ;			//07->14 = 0x0116
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x0000 ;			//07->15 = 0x0007
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;
	programming.Program_Block_Data = 0x3F00 ;			//07->16 = 0x3F08
	CMX7164_Write_WORD((CMX_WORD*)&programming);
	if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
		return 21;

*/


	/////////////////////////////////////////////////////////////////////////////////////////////////
		reg_done_select.Word_val = 0x0001 ;					//69	set REG_DONE -> PROG
		CMX7164_Write_WORD((CMX_WORD*)&reg_done_select);
		programming.Program_Block_Data = 0x0116 ;			//07->00 = 0x0116
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x00F7 ;			//07->01 = 0x0000
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0116 ;			//07->02 = 0x0116
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x00F7 ;			//07->03 = 0x0001
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0116 ;			//07->04 = 0x0116
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0037 ;			//07->05 = 0x0002
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0116 ;			//07->06 = 0x0116
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0017 ;			//07->07 = 0x0003
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0116 ;			//07->08 = 0x0116
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0006 ;			//07->09 = 0x0004
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0116 ;			//07->10 = 0x0116
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0004 ;			//07->11 = 0x0005
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0116 ;			//07->12 = 0x0116
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0002 ;			//07->13 = 0x0006
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0116 ;			//07->14 = 0x0116
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0x0000 ;			//07->15 = 0x0007
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;
		programming.Program_Block_Data = 0xFF08 ;			//07->16 = 0x3F08
		CMX7164_Write_WORD((CMX_WORD*)&programming);
		if(CMX7164_Check_Status(Reg_Done_Bit))				// wait until the value is registered
			return 21;

/////////////////////////////////////////////////////////////////////////////////////////////////
	signal_control.Word_val = 0x0000 ;
	CMX7164_Write_WORD((CMX_WORD*)&signal_control);		//select RX DC offset

	CMX994_Write(0x10 , 0);								//Reset
	CMX994_Write(0x11 , 0xC0);							//Bias En , Normal op. mode , 300-700 mhz , RX_ON
	CMX994_Write(0x12 , 0x14);							//MixPwr ,IQPwr,LNAPwr , DC-Norm , Divide - 2 ,ACRFlt Max
	CMX994_Write(0x13 , 0x00);							//No DC correction On I/Q Channels
	CMX994_Write(0x14 , 0x3f);							//Intermodulation default value
//	CMX994_Write(0x16 , 0x??);							//AGC is turned on
	CMX994_Write(0x25 , 0xF0);							//Enable LO input & disable VCO , TXO Div = 1
	CMX994_Write(0x11 , 0xC3);							//Bias En , Normal op. mode , 300-700 mhz , RX_ON
	return 0;
}

void CMX994_DC_Offset_Correction(void)
{
	int I_DC_Offset_local ,Q_DC_Offset_local ;
	unsigned char Applyed_DC_Offset ;

	CMX7164_Read_WORD((CMX_WORD*)&I_input_offset);
	CMX7164_Read_WORD((CMX_WORD*)&Q_input_offset);

//	I_DC_Offset_local = ((I_input_offset.I_Q_DC_Offset_Applied_to_the_I_Q_INPUTs*33)>>6)/10 ;
//	Q_DC_Offset_local = ((Q_input_offset.I_Q_DC_Offset_Applied_to_the_I_Q_INPUTs*33)>>6)/10 ;

	I_DC_Offset_local = (signed short)I_input_offset.I_Q_DC_Offset_Applied_to_the_I_Q_INPUTs ;
	Q_DC_Offset_local = (signed short)Q_input_offset.I_Q_DC_Offset_Applied_to_the_I_Q_INPUTs ;
	I_DC_Offset_local = (I_DC_Offset_local*1200)/65535 ;
	Q_DC_Offset_local = (Q_DC_Offset_local*1200)/65535 ;

//	printk("\r\n");
	if(Q_DC_Offset_local < -15 )
	{
		CMX994_Read(0xE3 , &Applyed_DC_Offset);
		if((Applyed_DC_Offset & 0xF0) >= 0x80 || (Applyed_DC_Offset & 0xF0) == 0)
		{
			if((Applyed_DC_Offset & 0xF0) != 0xF0)
			{
				Applyed_DC_Offset += 0x10 ;
				Applyed_DC_Offset |= 0x80 ;
			}
		}
		else
		{
			Applyed_DC_Offset -= 0x10 ;
			Applyed_DC_Offset &= 0x7F ;
		}
		CMX994_Write(0x13 , Applyed_DC_Offset);
//		printk("Q   %d  ",Q_DC_Offset_local);
//		printk("Q < -15\r\n");
	}
	else if(Q_DC_Offset_local > 15)
	{
		CMX994_Read(0xE3 , &Applyed_DC_Offset);
		if((Applyed_DC_Offset & 0xF0) > 0x80)
		{
			Applyed_DC_Offset -= 0x10 ;
			Applyed_DC_Offset |= 0x80 ;
		}
		else
		{
			if((Applyed_DC_Offset & 0x70) != 0x70)
			{
				Applyed_DC_Offset += 0x10 ;
				Applyed_DC_Offset &= 0x7F ;
			}
		}
		CMX994_Write(0x13 , Applyed_DC_Offset);
//		printk("Q   %d  ",Q_DC_Offset_local);
//		printk("Q > 15\r\n");
	}

	if(I_DC_Offset_local > 15 )
	{
		CMX994_Read(0xE3 , &Applyed_DC_Offset);
		if((Applyed_DC_Offset & 0x0F) >= 0x08 || (Applyed_DC_Offset & 0x0F) == 0)
		{
			if((Applyed_DC_Offset & 0x0F) != 0x0F)
			{
				Applyed_DC_Offset += 0x01 ;
				Applyed_DC_Offset |= 0x08 ;
			}
		}
		else
		{
			Applyed_DC_Offset -= 0x01 ;
			Applyed_DC_Offset &= 0xF7 ;
		}
		CMX994_Write(0x13 , Applyed_DC_Offset);
//		printk("I   %d  ",I_DC_Offset_local);
//		printk("I > 15\r\n");
	}
	else if(I_DC_Offset_local < -15)
	{
		CMX994_Read(0xE3 , &Applyed_DC_Offset);

		if((Applyed_DC_Offset & 0x0F) > 0x08)
		{
			Applyed_DC_Offset -= 0x01 ;
			Applyed_DC_Offset |= 0x08 ;
		}
		else
		{
			if((Applyed_DC_Offset & 0x07) != 0x07)
			{
				Applyed_DC_Offset += 0x01 ;
				Applyed_DC_Offset &= 0xF7 ;
			}
		}
		CMX994_Write(0x13 , Applyed_DC_Offset);
//		printk("I   %d  ",I_DC_Offset_local);
//		printk("I < -15\r\n");
	}
//	printk("%x\r\n",Applyed_DC_Offset);
}

int CMX994_Sleep(void)
{
	CMX994_Write(0x11 , 0xC1);
	return 1;
}

int CMX994_Wake(void)
{
	CMX994_Write(0x11 , 0xC3);
	return 1;
}

